/*** 
 * @_______________#########_______________________ 
 * @______________############_____________________ 
 * @______________#############____________________ 
 * @_____________##__###########___________________ 
 * @____________###__######_#####__________________ 
 * @____________###_#######___####_________________ 
 * @___________###__##########_####________________ 
 * @__________####__###########_####_______________ 
 * @________#####___###########__#####_____________ 
 * @_______######___###_########___#####___________ 
 * @_______#####___###___########___######_________ 
 * @______######___###__###########___######_______ 
 * @_____######___####_##############__######______ 
 * @____#######__#####################_#######_____ 
 * @____#######__##############################____ 
 * @___#######__######_#################_#######___ 
 * @___#######__######_######_#########___######___ 
 * @___#######____##__######___######_____######___ 
 * @___#######________######____#####_____#####____ 
 * @____######________#####_____#####_____####_____ 
 * @_____#####________####______#####_____###______ 
 * @______#####______;###________###______#________ 
 * @________##_______####________####______________ 
 * @
 * @Author: ipk518 121206530@qq.com
 * @Date: 2025-03-06 20:00:55
 * @LastEditors: ipk518 121206530@qq.com
 * @LastEditTime: 2025-06-06 15:24:12
 * @FilePath: /etws-sxk2307/src/packetResolver/webReply.hpp
 * @Description: 
 * @你把时间投在专业上，两三年，你就能在圈子里小有名气。四五年，你就能靠这个专业赚钱。过了10年以上，你就能成为这个领域的专家
 * @Copyright (c) 2025 by etws@quyujiang, All Rights Reserved. 
 */

#ifndef __WEB_REPLY__
#define __WEB_REPLY__

#include <iostream>
#include <string>
#include <vector>

#include <thread>
#include <mutex>
#include <condition_variable>
#include <unordered_map>
#include <future>
#include <chrono>
#include <functional>
// #include <c++/7/bits/algorithmfwd.h>

using namespace std;

#define CMD_REQUEST_TIMEOUT 2000

//代码的工作逻辑是在异步任务中等待每个设备的应答包，同时检测是否超时。
//如果在超时时长内收集到了所有应答包，则调用回调函数处理这些应答包；
//如果超时，则输出超时提示信息。这样就实现了在指定时长内收集和处理多个设备的应答包，并且具备了超时机制以增强程序的健壮性。
class Response {
public:
    Response() {}
    ~Response() { responseMap.clear(); };
    std::mutex m_resMtx;
    void addResponse(const std::string& device_id, const std::string& response)
    {
        std::lock_guard<std::mutex> lock(m_resMtx);
        responseMap[device_id] = response;
    };
    void collectResponses(const std::vector<std::string>& device_ids, 
    std::function<void(const std::string&)> callback, int timeout = -1)
    {
        std::vector<std::future<void>> futures;
        //在collectResponses方法内部，会为每个设备ID创建一个异步任务，每个任务会等待对应的应答包。
        auto startTime = std::chrono::steady_clock::now();
        for (const auto& device_id : device_ids) {
            futures.push_back(std::async(std::launch::async | std::launch::deferred, [this, device_id, startTime, timeout]() {
                while (responseMap.find(device_id) == responseMap.end()) {
                    // 等待应答包
                    // 在容器中搜索键值等于 device_id 的元素，如果找到，则返回一个指向该元素的迭代器，
                    // 否则返回一个指向responseMap.end()的迭代器。
                    if(timeout >= 0) {
                        if (std::chrono::steady_clock::now() - startTime > std::chrono::milliseconds(timeout)) {
                            // 超时处理
                            qlog_w("Timeout occurred while waiting for %s responses.",device_id.data());
                            responseMap[device_id] = "Timeout";
                        }
                    }
                    std::this_thread::sleep_for(std::chrono::milliseconds(10));
                }
            }));
        }
        //在循环中检查每个异步任务的状态，如果超过了设置的超时时长（5秒），则输出超时提示信息并结束等待。
        //如果在超时时长内收集到了所有应答包，会调用回调函数处理每个应答包。
        
        
        for (auto& future : futures) {
            future.get();
        }
        callback(std::string("Finish waiting."));
    };

    int Result(const std::string& device_id) 
    {
        int ret = 0;
        if (responseMap.find(device_id) != responseMap.end()) {
            ret = (strcmp("Timeout", responseMap[device_id].data()) == 0)?
            0:1;
        }
        return ret;
    }

    void wait(std::vector<std::string>& device_ids , int timeout = CMD_REQUEST_TIMEOUT)
    {
        //调用collector对象的collectResponses方法，传入设备ID向量、处理应答包的回调函数和超时时长（这里设置为5秒）
        collectResponses(device_ids, [](const std::string& response) {
            qlog_i("%s",response.data());
        }, timeout);
    }
    
private:
    std::unordered_map<std::string, std::string> responseMap;
};





#endif